﻿using DevExpress.ExpressApp;
using DevExpress.ExpressApp.ApplicationBuilder;
using DevExpress.ExpressApp.ApplicationBuilder.Internal;
using DevExpress.ExpressApp.DC;
using DevExpress.ExpressApp.Security;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

namespace XAF_EFCore_Sample.Module.EFCoreObjectSpaces;

public static class CustomEFCoreObjectSpaceProviderBuilderExtensions
{
    public static DbContextServiceBasedBuilder<TContext> AddCustomEFCore<TContext>(this IObjectSpaceProviderServiceBasedBuilder<TContext> builder) where TContext : IXafApplicationBuilder<TContext>, IAccessor<IServiceCollection>
    {
        var dbContextBuilder = new DbContextServiceBasedBuilder<TContext>(builder)
        {
            IsSecured = true,
            SpecialConfigureOptions = (serviceProvider, options) =>
            {
                options.UseSecurity(serviceProvider.GetRequiredService<ISelectDataSecurityProvider>());
            }
        };

        builder.Add(serviceProvider =>
        {
            object dbContextFactory = dbContextBuilder.GetDbContextFactory(serviceProvider);
            return CreateSecuredEFCoreObjectSpaceProvider(serviceProvider.GetRequiredService<ISelectDataSecurityProvider>(), dbContextFactory, serviceProvider.GetRequiredService<ITypesInfo>());
        });

        return dbContextBuilder;
    }

    private static IObjectSpaceProvider CreateSecuredEFCoreObjectSpaceProvider(ISelectDataSecurityProvider selectProvider, object dbContextFactory, ITypesInfo typesInfo)
    {
        var dbContextType = dbContextFactory.GetType().GenericTypeArguments[0];
        var objectSpaceProviderType = typeof(CustomEFCoreObjectSpaceProvider<>).MakeGenericType(dbContextType);
        return (IObjectSpaceProvider)Activator.CreateInstance(objectSpaceProviderType, selectProvider, dbContextFactory, typesInfo);
    }
}
